package pkg

import (
	"context"
	"errors"
	"fmt"

	"github.com/smartwalle/alipay/v3"
)

// PaymentMethod 支付方式枚举
type PaymentMethod string

const (
	PaymentMethodAlipay PaymentMethod = "alipay"
)

// PaymentService 支付服务接口
type PaymentService interface {
	Pay(_ context.Context, orderNo, amount string, params map[string]interface{}) (string, error)
}

// PaymentFactory 支付工厂
type PaymentFactory struct{}

// NewPaymentFactory 支付工厂
func NewPaymentFactory() *PaymentFactory {
	return &PaymentFactory{}
}

// CreatePaymentService 创建支付服务实例
func (f *PaymentFactory) CreatePaymentService(method PaymentMethod) (PaymentService, error) {
	switch method {
	case PaymentMethodAlipay:
		return NewAlipayService(), nil
	default:
		return nil, errors.New("不支持的支付方式")
	}
}

// AlipayService 支付宝支付服务
type AlipayService struct{}

// NewAlipayService 创建支付宝支付服务
func NewAlipayService() *AlipayService {
	return &AlipayService{}
}

// Pay 支付宝支付
func (s *AlipayService) Pay(_ context.Context, orderCode, amount string, params map[string]interface{}) (string, error) {
	appId := "2021000149636760"
	var privateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC3NICeWfd3a62PWuDUqLilh8kEjXrA4wBkvYFkAJmmuzLJUbe7ImkiIj6HQkm3BMwVQ5Dc5qzgENczodNhViKwwLOHkelybwrxhIJzH9Js0ZeqVmhdJKrWssLKs95I1ym7eupy0kYv5vWG1hXoylmW/CkmgqwtcYxBzrK3UvMkSfU14TSQOboC2SBVVjZ0LRd/8HB4LxfKtOvn7cKX/VvB/jh/BCG40h/NgR7vE9mX4v4L/DFuLPqYGLYjtpI96xWupd7Ty1JHrr1f1vM6VHYTqS5exyARzY3BCG7LMwVjEOTFceIp5y84zJ/xT1/52Xcnu8JTUAoriCsaksukpv9jAgMBAAECggEAah+cnZ3JzsBuIktnT2iIxUI5vExkHhWgpbpsmEwMtVtc2OdgQaN2ORKTG/DXGJBL08l2wa9R1t2Ke1szQgAOSkrl9BMeom4Wbb7vfdaiIuzqKP6yp7nUyFd2pMq6aYFRqEtUQbzycU8dTMT4ngeRC/f3sloheJV8xKYCOlVviMXe1vlpGDlHBSR/FR5pXQMXBJrhm6Yc3yaxVNJ/dCxEiho3Jd+2XKtQ9B61IqlufDhAZBeG4Ov31uy7oHgb0DLi9cWt6AsOaaisIWwqTaxGacjSUDvwq2mVQTIJ1vANTGHijhht2en7PF6H72xZjNFEy/qUGIrX4TkjZYHd17o70QKBgQDr5bf/0dk8LkBp6oNn4rUSUUaVREZTwcqxmqYt1KXElhrs17xspkKO44103rTBYA+0JySASCncazlAleeel5Ff0jCAjWxhiIyAlrwMnI0/3LuZM57MLtLxiLPg9W5lrjeckk8LE4+vXz+PJK9z+PcjEfyRLMAc/vvjhfKVJYhimQKBgQDG0UMGrNdv1cXs9C02aDkcXIauY6XQTlkXxau7equaEZAx327zzcl19SC/v438vbQ5ccYJtqAnOcToHA4+VLrxSVAgZ+7cpXzsmVwZFA27127d3LWyd6EBjgKS/nAzl9uMWUid+1XoLnO9+Ghgae1pFQ510x6kH0pRctU0+2ZrWwKBgEhrxglry12GdZAOxzjliOGOwjShOVYNcMUFzW7Uke/AhZOgx+AzSsvDYHI4zRVxAGE2gyY/AVsCMBl77BfsQF1CklFlGZj36uqvXBwjE9o/Ufi+uEnHNkugxFiUAMiGq9wNruafosUcYM75XEQmcvj5VKjdLD26qmo3fTn8w9pBAoGAcG/R7wl6gOWtnHbuxtEkUzTEegUite5JFleU6l7SgzwhhwLsFXcw0sPBNI+ZNfD25nHAZKfiZKyX/gg3yepTGreyV9FPVXtFbezBF/GuXqfULCZwnzBmXqG4NPct7w+XewTXO3jzOW5jyHCeXsApIn9lAR9XOcv0VKGTj/YJEvcCgYARGVVWQZauMQndo1jxQo+b3gu673+VGckue/iTrI5SKW98srOIJW4sWM1uAiCh+ADiMVYd3SD/4VugoTPm4mpNDGcjO/yOZtH8dj8nGF2Po6Mu5uv/1s1SPsPiNbqEBX3+q2cS7W8FEk2Eedj0H+jOlMRSiA1uPfO/jGXI8zYgoA==" // 必须，上一步中使用 RSA签名验签工具 生成的私钥
	var client, err = alipay.New(appId, privateKey, false)
	if err != nil {
		fmt.Println(err)
		return "", nil
	}
	var p = alipay.TradeWapPay{}
	p.NotifyURL = "http://xxx"
	p.ReturnURL = "http://xxx"
	p.Subject = "外卖支付"
	p.OutTradeNo = orderCode
	p.TotalAmount = amount
	p.ProductCode = "QUICK_WAP_WAY"

	url, err := client.TradeWapPay(p)
	if err != nil {
		fmt.Println(err)
	}

	// 这个 payURL 既是用于打开支付宝支付页面的 URL，可将输出的内容复制，到浏览器中访问该 URL 即可打开支付页面。
	var payURL = url.String()
	fmt.Println(payURL)
	return payURL, nil

}

// Refund 支付宝退款
func (s *AlipayService) Refund(ctx context.Context, orderNo string, refundNo string, amount float64) error {
	// 实际项目中应该调用支付宝开放平台API
	fmt.Printf("Alipay refund: orderNo=%s, refundNo=%s, amount=%.2f\n", orderNo, refundNo, amount)
	return nil
}

// Query 支付宝查询
func (s *AlipayService) Query(ctx context.Context, orderNo string) (map[string]interface{}, error) {
	// 实际项目中应该调用支付宝开放平台API
	return map[string]interface{}{
		"order_no": orderNo,
		"status":   "pending",
		"method":   "alipay",
	}, nil
}

// Verify 支付宝回调验证
func (s *AlipayService) Verify(ctx context.Context, notification map[string]interface{}) (string, float64, error) {
	// 实际项目中应该验证签名等
	orderNo, ok := notification["order_no"].(string)
	if !ok {
		return "", 0, errors.New("缺少订单号")
	}

	amount, ok := notification["amount"].(float64)
	if !ok {
		return orderNo, 0, errors.New("缺少金额")
	}

	return orderNo, amount, nil
}
